gsk: Add GskMatrixCategory
authorBenjamin Otte <otte@redhat.com>
Tue, 19 Feb 2019 05:52:36 +0000 (06:52 +0100)
committerBenjamin Otte <otte@redhat.com>
Thu, 21 Feb 2019 18:47:27 +0000 (19:47 +0100)
We'll use that soon.

gsk/gskrendernodeimpl.c
gsk/gskrendernodeprivate.h
gtk/inspector/recorder.c

index 8b704aeddaf668b24c121c6abe7283266e40fb37..34dd509d1fd1abf2b277e6af745ec22a4d43d0c4 100644 (file)
@@ -2387,6 +2387,7 @@ struct _GskTransformNode
 
   GskRenderNode *child;
   graphene_matrix_t transform;
+  GskMatrixCategory category;
 };
 
 static void
@@ -2422,7 +2423,7 @@ gsk_transform_node_draw (GskRenderNode *node,
     }
 }
 
-#define GSK_TRANSFORM_NODE_VARIANT_TYPE "(dddddddddddddddduv)"
+#define GSK_TRANSFORM_NODE_VARIANT_TYPE "(idddddddddddddddduv)"
 
 static GVariant *
 gsk_transform_node_serialize (GskRenderNode *node)
@@ -2433,6 +2434,7 @@ gsk_transform_node_serialize (GskRenderNode *node)
   graphene_matrix_to_float (&self->transform, mat);
 
   return g_variant_new (GSK_TRANSFORM_NODE_VARIANT_TYPE,
+                        self->category,
                         (double) mat[0], (double) mat[1], (double) mat[2], (double) mat[3],
                         (double) mat[4], (double) mat[5], (double) mat[6], (double) mat[7],
                         (double) mat[8], (double) mat[9], (double) mat[10], (double) mat[11],
@@ -2448,6 +2450,7 @@ gsk_transform_node_deserialize (GVariant  *variant,
   graphene_matrix_t transform;
   double mat[16];
   guint32 child_type;
+  gint32 category;
   GVariant *child_variant;
   GskRenderNode *result, *child;
 
@@ -2455,6 +2458,7 @@ gsk_transform_node_deserialize (GVariant  *variant,
     return NULL;
 
   g_variant_get (variant, GSK_TRANSFORM_NODE_VARIANT_TYPE,
+                 &category,
                  &mat[0], &mat[1], &mat[2], &mat[3],
                  &mat[4], &mat[5], &mat[6], &mat[7],
                  &mat[8], &mat[9], &mat[10], &mat[11],
@@ -2475,7 +2479,7 @@ gsk_transform_node_deserialize (GVariant  *variant,
                                        mat[12], mat[13], mat[14], mat[15]
                                    });
 
-  result = gsk_transform_node_new (child, &transform);
+  result = gsk_transform_node_new_with_category (child, &transform, category);
 
   gsk_render_node_unref (child);
 
@@ -2508,15 +2512,39 @@ GskRenderNode *
 gsk_transform_node_new (GskRenderNode           *child,
                         const graphene_matrix_t *transform)
 {
-  GskTransformNode *self;
-
   g_return_val_if_fail (GSK_IS_RENDER_NODE (child), NULL);
   g_return_val_if_fail (transform != NULL, NULL);
 
+  return gsk_transform_node_new_with_category (child, transform, GSK_MATRIX_CATEGORY_UNKNOWN);
+}
+
+/*<private>
+ * gsk_transform_node_new_with_category:
+ * @child: The node to transform
+ * @transform: The transform to apply
+ * @category: The category @transform belongs to
+ *
+ * Creates a #GskRenderNode that will transform the given @child
+ * with the given @transform.
+ *
+ * The given @category will be used by renderers for optimizations and must
+ * be correct. If you do not know the category of @transform, use
+ * %GSK_MATRIX_CATEGORY_UNKNOWN.
+ *
+ * Returns: A new #GskRenderNode
+ **/
+GskRenderNode *
+gsk_transform_node_new_with_category (GskRenderNode           *child,
+                                      const graphene_matrix_t *transform,
+                                      GskMatrixCategory        category)
+{
+  GskTransformNode *self;
+
   self = (GskTransformNode *) gsk_render_node_new (&GSK_TRANSFORM_NODE_CLASS, 0);
 
   self->child = gsk_render_node_ref (child);
   graphene_matrix_init_from_matrix (&self->transform, transform);
+  self->category = category;
 
   graphene_matrix_transform_bounds (&self->transform,
                                     &child->bounds,
@@ -2552,6 +2580,16 @@ gsk_transform_node_peek_transform (GskRenderNode *node)
   return &self->transform;
 }
 
+GskMatrixCategory
+gsk_transform_node_get_category (GskRenderNode *node)
+{
+  GskTransformNode *self = (GskTransformNode *) node;
+
+  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TRANSFORM_NODE), GSK_MATRIX_CATEGORY_UNKNOWN);
+
+  return self->category;
+}
+
 /*** GSK_OFFSET_NODE ***/
 
 typedef struct _GskOffsetNode GskOffsetNode;
index 145fec0955d8f3e09fecd92bf07be3a59b9b26ed..1f0565cfabe337aedb06fdb8cce47749bcd1d99d 100644 (file)
@@ -6,6 +6,44 @@
 
 G_BEGIN_DECLS
 
+/*<private>
+ * GskMatrixCategory:
+ * @GSK_MATRIX_CATEGORY_UNKNOWN: The category of the matrix has not been
+ *     determined.
+ * @GSK_MATRIX_CATEGORY_ANY: Analyzing the matrix concluded that it does
+ *     not fit in any other category.
+ * @GSK_MATRIX_CATEGORY_INVERTIBLE: The matrix is linear independant and
+ *     should therefor be invertible. Note that this is not guaranteed
+ *     to actually be true due to rounding errors when inverting.
+ * @GSK_MATRIX_CATEGORY_2D: The matrix is a 2D matrix. This is equivalent
+ *     to graphene_matrix_is_2d() returning %TRUE. In particular, this
+ *     means that Cairo can deal with the matrix.
+ * @GSK_MATRIX_CATEGORY_2D_AFFINE: The matrix is a combination of 2D scale
+ *     and 2D translation operations. In particular, this means that any
+ *     rectangle can be transformed exactly using this matrix.
+ * @GSK_MATRIX_CATEGORY_2D_TRANSLATE: The matrix is a 2D translation.
+ * @GSK_MATRIX_CATEGORY_IDENTITY: The matrix is the identity matrix.
+ *
+ * The categories of matrices relevant for GSK and GTK. Note that any
+ * category includes matrices of all later categories. So if you want
+ * to for example check if a matrix is a 2D matrix,
+ * `category >= GSK_MATRIX_CATEGORY_2D` is the way to do this.
+ *
+ * Also keep in mind that rounding errors may cause matrices to not
+ * conform to their categories. Otherwise, matrix operations done via
+ * mutliplication will not worsen categories. So for the matrix
+ * multiplication `C = A * B`, `category(C) = MIN (category(A), category(B))`.
+ */
+typedef enum
+{
+  GSK_MATRIX_CATEGORY_UNKNOWN,
+  GSK_MATRIX_CATEGORY_ANY,
+  GSK_MATRIX_CATEGORY_INVERTIBLE,
+  GSK_MATRIX_CATEGORY_2D_AFFINE,
+  GSK_MATRIX_CATEGORY_2D_TRANSLATE,
+  GSK_MATRIX_CATEGORY_IDENTITY
+} GskMatrixCategory;
+
 typedef struct _GskRenderNodeClass GskRenderNodeClass;
 
 #define GSK_IS_RENDER_NODE_TYPE(node,type) (GSK_IS_RENDER_NODE (node) && (node)->node_class->node_type == (type))
@@ -58,6 +96,11 @@ GskRenderNode * gsk_render_node_deserialize_node (GskRenderNodeType          typ
 GskRenderNode * gsk_cairo_node_new_for_surface   (const graphene_rect_t    *bounds,
                                                   cairo_surface_t          *surface);
 
+GskRenderNode *         gsk_transform_node_new_with_category    (GskRenderNode                  *child,
+                                                                 const graphene_matrix_t        *transform,
+                                                                 GskMatrixCategory               category);
+GskMatrixCategory       gsk_transform_node_get_category         (GskRenderNode                  *node);
+
 GskRenderNode * gsk_text_node_new_with_bounds     (PangoFont                *font,
                                                    PangoGlyphString         *glyphs,
                                                    const GdkRGBA            *color,
index 26ae9cbdd2c45555e5a473cd2551c120146a7ada..0a56aefb8aec8a6db631b13cb29581625804e175 100644 (file)
@@ -901,6 +901,14 @@ populate_render_node_properties (GtkListStore  *store,
 
     case GSK_TRANSFORM_NODE:
       {
+        static const char * category_names[] = {
+          [GSK_MATRIX_CATEGORY_UNKNOWN] = "unknown",
+          [GSK_MATRIX_CATEGORY_ANY] = "any",
+          [GSK_MATRIX_CATEGORY_INVERTIBLE] = "invertible",
+          [GSK_MATRIX_CATEGORY_2D_AFFINE] = "2D affine",
+          [GSK_MATRIX_CATEGORY_2D_TRANSLATE] = "2D transform",
+          [GSK_MATRIX_CATEGORY_IDENTITY] = "identity"
+        };
         float f[16];
         guint i;
 
@@ -913,6 +921,7 @@ populate_render_node_properties (GtkListStore  *store,
             add_text_row (store, i == 0 ? "Matrix" : "", row_string);
             g_free (row_string);
           }
+        add_text_row (store, "Category", category_names[gsk_transform_node_get_category (node)]);
       }
       break;